#include "workui.h"
#include "ui_workui.h"
#include<QDebug>
#include<QPair>
#include<QStringList>
#include <QtMath>    // 用于 qSqrt 和 qPow
#include <algorithm> // 用于 std::sort
#include <QList>
WorkUI::WorkUI(QWidget *parent,QString nn,QString id,QUdpSocket* udp) :
    QMainWindow(parent),
    ui(new Ui::WorkUI)
{
    name=nn;
    ID=id;
    this->udp=udp;
    qDebug()<<name;
    ui->setupUi(this);
    connect(ui->mapwidget,&Mapwidget::changepos,this,&WorkUI::changeposact);
    ui->mapwidget->identity=0;
    connect(this->udp,&QUdpSocket::readyRead,this,&WorkUI::Udphandle);
    ui->locationButton_3->setEnabled(false);
}

WorkUI::~WorkUI()
{
    delete ui;
}
QList<long long> WorkUI::findNearestAvailableCarsForOrder(
    long long orderId,
    const QMap<long long, QPoint>& carFreeMap,
    const QMap<long long, QPoint>& orderStartMap,
    const QMap<long long, int>& orderWeightsMap,
    const QMap<long long, int>& carCapacitiesMap
) {
    QList<long long> nearestCarIds; // 最终返回的车辆ID列表

//    // 1. 获取订单详情：起点坐标和所需重量
//    if (!orderStartMap.contains(orderId) || !orderWeightsMap.contains(orderId)) {
//        qDebug() << "错误: 订单ID" << orderId << "不存在或缺少起点/重量信息。";
//        return nearestCarIds; // 返回空列表
//    }

    QPoint orderPickupLocation = orderStartMap.value(orderId);
    int requiredWeight = orderWeightsMap.value(orderId);

    qDebug() << "--- 正在为订单" << orderId << "查找车辆 ---";
    qDebug() << "订单起点:" << orderPickupLocation << ", 所需重量:" << requiredWeight;

    QList<CarDistance> eligibleCars; // 存储符合条件的车辆及其距离

    // 2. 遍历空闲车辆，筛选并计算距离
    for (auto it = carFreeMap.constBegin(); it != carFreeMap.constEnd(); ++it) {
        long long carId = it.key();
        QPoint carLocation = it.value();

        // 检查该车辆是否有最大载重信息
        if (!carCapacitiesMap.contains(carId)) {
            qDebug() << "警告: 车辆" << carId << "缺少最大载重信息，跳过。";
            continue;
        }

        int carMaxCapacity = carCapacitiesMap.value(carId);

        // 检查车辆的最大载重是否满足订单所需重量
        if (carMaxCapacity >= requiredWeight) {
            // 3. 计算车辆到订单起点的欧几里得距离
            double dist = qSqrt(qPow(carLocation.x() - orderPickupLocation.x(), 2) +
                                qPow(carLocation.y() - orderPickupLocation.y(), 2));

            eligibleCars.append({carId, dist}); // 添加到符合条件的列表
            qDebug() << "  - 车辆" << carId << " (位置:" << carLocation << ", 载重:" << carMaxCapacity << ") 满足要求，距离:" << dist;
        } else {
            qDebug() << "  - 车辆" << carId << " (位置:" << carLocation << ", 载重:" << carMaxCapacity << ") 载重不足，跳过。";
        }
    }

    // 4. 对符合条件的车辆按距离进行排序 (从近到远)
    std::sort(eligibleCars.begin(), eligibleCars.end());

    // 5. 将排序后的车辆ID添加到结果列表
    for (const auto& car : eligibleCars) {
        nearestCarIds.append(car.carId);
    }

    if (nearestCarIds.isEmpty()) {
        qDebug() << "--- 未找到符合订单" << orderId << "要求的空闲车辆。---";
    } else {
        qDebug() << "--- 为订单" << orderId << "找到的车辆ID列表 (按距离从近到远):" << nearestCarIds << "---";
    }

    return nearestCarIds;
}

void WorkUI::closeEvent(QCloseEvent *e)
{
    QString news="Q,"+ID+",merchant";
    QNetworkDatagram nw(news.toUtf8(),QHostAddress("127.0.0.1"),12345);
    udp->writeDatagram(nw);
}
void WorkUI::on_locationButton_clicked()
{
    nowlocal=ui->mapwidget->location;
    emit ui->mapwidget->chlocationok(1);
    QString a="A,"+ID+","+"merchant,"+QString().number(nowlocal.x())+","+QString().number(nowlocal.y())+","+name;
    QNetworkDatagram q(a.toUtf8(),QHostAddress("127.0.0.1"),12345);
    udp->writeDatagram(q);
    qDebug()<<a;
    qDebug() << "数据报已发送到" << q.destinationAddress().toString() << ":" << q.destinationPort();

}

void WorkUI::on_finallButton_clicked()
{
    finallocal=ui->mapwidget->finall;
    emit ui->mapwidget->chfinallok(1);
}

void WorkUI::changeposact()
{
    ui->loc->setText("("+QString().number(ui->mapwidget->location.x())+","+QString().number(ui->mapwidget->location.y())+")");
    ui->fin->setText("("+QString().number(ui->mapwidget->finall.x())+","+QString().number(ui->mapwidget->finall.y())+")");
}

void WorkUI::Udphandle()
{
    const QNetworkDatagram& responseDatagram = udp->receiveDatagram();
     QString response = responseDatagram.data();
     qDebug()<<response;

     if(response[0]=='A')   //增加坐标
     {
         QStringList parts = response.split(',');
         for (const QString &part : parts) {
                qDebug() << part;
            }

         int a=parts[1].toInt();
         QPoint p(parts[3].toInt(),parts[4].toInt());
         if(parts[2]=="merchant")
         {
             emit ui->mapwidget->chmarchantin(a,p);
         }
         else
         {
             emit ui->mapwidget->chcarfreein(a,p);
             emit ui->mapwidget->chcarweight(a,parts[6].toInt());
         }
     }
    else if(response[0]=='D')
     {
         QStringList parts=response.split(',');
         for (const QString &part : parts) {
                qDebug() << part;
            }
         long long i=parts[1].toLong();
         QPoint p(parts[3].toInt(),parts[4].toInt());
         QPoint p2(parts[5].toInt(),parts[6].toInt());
         int w=parts[7].toInt();
         emit ui->mapwidget->chorderstartin(i,p);
         emit ui->mapwidget->chorderendin(i,p2);
         emit ui->mapwidget->chorderi(i);
         emit ui->mapwidget->chweight(i,w);
     }
    else if(response[0]=='o'&&response[1]=='k')
     {
         qDebug()<<"start";
     }
     else if(response[0]=='E')
     {
         QStringList parts=response.split(',');
         for (const QString &part : parts) {
                qDebug() << part;
            }
         int i=0;
         for(i=1;i<parts.size();i++)
         {
             ui->listWidget->addItem(parts[i]);
         }
     }
     else if(response[0]=='O')
     {
         QStringList parts=response.split(',');
         for (const QString &part : parts) {
                qDebug() << part;
            }
         int i=0;
         for(i=1;i<parts.size();i++)
         {
            long long p=parts[i].toLong();
            emit ui->mapwidget->chcarbuzyin(p,ui->mapwidget->carfree[p]);
            emit ui->mapwidget->chcarfreerm(p);
         }
     }
     else if(response[0]=='R')
     {
         QStringList parts=response.split(',');
         for (const QString &part : parts) {
                qDebug() << part;
            }
         int i=0;
         for(i=1;i<parts.size();i++)
         {
             long long p=parts[i].toLong();
             emit ui->mapwidget->chcarfreein(p,ui->mapwidget->carbuzy[p]);
             emit ui->mapwidget->chcarbuzyrm(p);
         }
     }
     else if(response[0]=='Q')
     {
         QStringList parts=response.split(',');
        long long d=parts[1].toULong();
        if(parts[2]=="merchant")
        {
            emit ui->mapwidget->chmarchantrm(d);
        }
        else
        {
            emit ui->mapwidget->chcarfreerm(d);

        }
     }
     else if(response[0]=='C')
     {
         QStringList parts=response.split(',');
         for (const QString &part : parts) {
                qDebug() << part;
            }
         long long d=parts[1].toULong();
         QPoint p(parts[3].toUInt(),parts[4].toUInt());
         if(parts[2]=="merchant")
         {
             emit ui->mapwidget->chmarchantin(d,p);
         }
         else
         {
             if(ui->mapwidget->carbuzy.find(d)!=ui->mapwidget->carbuzy.end())
             {
                 emit ui->mapwidget->chcarbuzyin(d,p);
             }
             else
             {
                 emit ui->mapwidget->chcarfreein(d,p);
             }
         }
     }
     else if(response.startsWith("finish"))
     {
          QStringList parts=response.split(',');
          long long ordernum=parts[1].toLong();
          if(ordernum==ui->mapwidget->noworder)
          {
              emit ui->mapwidget->chlocationok(0);
              emit ui->mapwidget->chfinallok(0);
              emit ui->mapwidget->chroadclear();
              emit ui->mapwidget->chorderr(ordernum);
              emit ui->mapwidget->chorderendrm(ordernum);
              emit ui->mapwidget->changeorderstartrm(ordernum);
              ui->listWidget->clear();
              ui->locationButton_3->setEnabled(false);
          }
     }
     emit ui->mapwidget->updateemit();
}

QPair<int, int> findBoundingGridPointIndices(const QPoint& targetPoint, const QVector<QPoint>& gridPoints, int xTolerance, int yTolerance)
{
    if (gridPoints.size() < 2) {
        qDebug() << "错误：网格点不足，无法找到边界点。";
        return qMakePair(-1, -1);
    }

    QVector<QPair<double, int>> candidatePointsByX; // 存储 {到目标点的距离平方, 索引}

    // 1. 第一遍筛选：根据 X 坐标在容忍范围内进行筛选
    for (int i = 0; i < gridPoints.size(); ++i) {
        const QPoint& p = gridPoints.at(i);
        if (std::abs(static_cast<double>(targetPoint.x()) - p.x()) <= xTolerance) {
            // 计算完整的 2D 距离平方，用于后续排序
            double distSquared = (static_cast<double>(targetPoint.x()) - p.x()) * (static_cast<double>(targetPoint.x()) - p.x()) +
                                 (static_cast<double>(targetPoint.y()) - p.y()) * (static_cast<double>(targetPoint.y()) - p.y());
            candidatePointsByX.append(qMakePair(distSquared, i));
        }
    }

    if (candidatePointsByX.size() < 2) {
        qDebug() << "在 X 容忍范围内没有足够的候选点（" << xTolerance << "）。数量：" << candidatePointsByX.size();
        return qMakePair(-1, -1);
    }

    // 2. 第二遍筛选：在 X 筛选后的点中，根据 Y 坐标在容忍范围内进一步筛选
    QVector<QPair<double, int>> finalCandidates; // 存储 {到目标点的距离平方, 索引}

    for (const auto& candidate : candidatePointsByX) {
        int index = candidate.second;
        const QPoint& p = gridPoints.at(index);

        if (std::abs(static_cast<double>(targetPoint.y()) - p.y()) <= yTolerance) {
            finalCandidates.append(candidate); // 如果通过了 Y 容忍筛选，则将其添加为最终候选点
        }
    }

    if (finalCandidates.size() < 2) {
        qDebug() << "应用 Y 容忍范围（" << yTolerance << "）后没有足够的最终候选点。数量：" << finalCandidates.size();
        return qMakePair(-1, -1);
    }

    // 3. 对最终候选点按其到 targetPoint 的总体 2D 距离进行排序
    //    并选择最近的两个不同点。
    std::sort(finalCandidates.begin(), finalCandidates.end(), [](const QPair<double, int>& a, const QPair<double, int>& b){
        return a.first < b.first;
    });

    int firstIndex = finalCandidates.at(0).second;
    int secondIndex = finalCandidates.at(1).second;

    // 确保找到的两个点是不同的（如果 finalCandidates.size() >= 2，理论上应该不同，但为了健壮性检查一下）
    if (firstIndex == secondIndex) {
        // 这种情况理论上不应该发生，除非同一个点以某种方式被添加了两次。
        qDebug() << "在 X 和 Y 容忍范围内只找到一个不同的点。";
        return qMakePair(-1, -1);
    }
    return qMakePair(firstIndex+1, secondIndex+1);
}
void WorkUI::on_locationButton_2_clicked()
{
    QString s=ID+"1";
    while(ui->mapwidget->order.find(s.toLong())!=ui->mapwidget->order.end())
    {
        s.push_back("1");
    }
    orderid=s;
    emit ui->mapwidget->chnoworder(s.toULong());
    emit ui->mapwidget->chorderstartin(ui->mapwidget->noworder,nowlocal);
    emit ui->mapwidget->chorderendin(ui->mapwidget->noworder,finallocal);
    emit ui->mapwidget->chweight(ui->mapwidget->noworder,ui->spinBox->value());
    QString news="D,"+s+","+ID+","+QString().number(nowlocal.x())+","+QString().number(nowlocal.y())+","+QString().number(finallocal.x())+","+QString().number(finallocal.y())+","+ui->spinBox->text();
    QNetworkDatagram nw(news.toUtf8(),QHostAddress("127.0.0.1"),12345);
    udp->writeDatagram(nw);
    qDebug()<<news;
    QPair<int,int> a=findBoundingGridPointIndices(nowlocal,ui->mapwidget->gridPoints,nowlocal.x(),nowlocal.y());
    QPair<int,int> b=findBoundingGridPointIndices(finallocal,ui->mapwidget->gridPoints,finallocal.x(),finallocal.y());
    int dir=0;//0北 1东北 2东 3东南 4南 5 西南 6 西 7西北
    if(finallocal.y()>nowlocal.y())
    {
        if(finallocal.x()>nowlocal.x())
        {
            dir=1;
        }
        else if(finallocal.x()==nowlocal.x())
            dir=0;
        else
            dir=7;
    }
    else
    {
        if(finallocal.x()>nowlocal.x())
        {
            dir=3;
        }
        else if(finallocal.x()==nowlocal.x())
            dir=4;
        else
            dir=5;
    }
    qDebug()<<a;
    qDebug()<<b;
    int obegin;
    int oend;
    QVector<QPoint>& m=ui->mapwidget->gridPoints;
    QPoint a1=m[a.first-1];
    QPoint a2=m[a.second-1];
    QPoint b1=m[b.first-1];
    QPoint b2=m[b.second-1];
    if(abs(a1.x()-a2.x())<15)
    {
        //同一列
        if(a1.y()>a2.y())
        {
            if(dir<3||dir==7)
            {
                obegin=a.first;
            }
            else
                obegin=a.second;
        }
        else
        {

            if(dir<3||dir==7)
            {
                obegin=a.second;
            }
            else
                obegin=a.first;
        }
    }
    else
    {
        //同一行
        if(a1.x()>a2.x())
        {
            if(dir<4)
            {
                obegin=a.first;
            }
            else
                obegin=a.second;
        }
        else
        {
            if(dir<4)
            {
                obegin=a.second;
            }
            else
                obegin=a.first;
        }
    }
    if(abs(b1.x()-b2.x())<15)
    {
        //同一列
        if(b1.y()>b2.y())
        {
            if(dir<3||dir==7)
            {
                oend=b.second;
            }
            else
                oend=b.first;
        }
        else
        {

            if(dir<3||dir==7)
            {
                oend=b.first;
            }
            else
                oend=b.second;
        }
    }
    else
    {
        //同一行
        if(b1.y()>b2.y())
        {
            if(dir<3||dir==7)
            {
                oend=b.first;
            }
            else
                oend=b.second;
        }
        else
        {

            if(dir<3||dir==7)
            {
                oend=b.second;
            }
            else
                oend=b.first;
        }
    }
    pair<queue<int>, int> re=result().dijkstra(obegin,oend);

    emit ui->mapwidget->chroadclear();
    emit ui->mapwidget->chroadin(nowlocal);
    queue<int>& q=re.first;
    while(!q.empty())
    {
        emit ui->mapwidget->chroadin(m[q.front()-1]);
        q.pop();
    }
    emit ui->mapwidget->chroadin(finallocal);
    emit ui->mapwidget->updateemit();

    QList<long long> carl=findNearestAvailableCarsForOrder(ui->mapwidget->noworder,ui->mapwidget->carfree,ui->mapwidget->orderstart,ui->mapwidget->weight,ui->mapwidget->carweight);
    news="F,";
    qDebug()<<carl.size();
    news+=QString().number(ui->mapwidget->noworder);
    ui->listWidget->clear();
    qDebug()<<"here order:"<<ui->mapwidget->noworder<<ui->mapwidget->orderstart[ui->mapwidget->noworder]<<ui->mapwidget->orderend[ui->mapwidget->noworder]<<','<<ui->mapwidget->carweight[ui->mapwidget->noworder];
    qDebug()<<"heres carfree";
    for(auto i:ui->mapwidget->carfree)
    {
        qDebug()<<i<<',';
    }
    for(auto i:ui->mapwidget->carweight)
    {
        qDebug()<<i<<',';
    }
    int flag=0;
    qDebug()<<"match";
    for(auto i:carl)
    {       
        ui->listWidget->addItem(QString().number(i));
        ui->locationButton_3->setEnabled(true);
        flag=1;
    }
    if(flag==0)
        return;


   carls=carl;
}

void WorkUI::on_locationButton_3_clicked()
{
    QString news="F,";
    QString nn="O,"+orderid;
    news+=QString().number(ui->mapwidget->noworder);
    for(auto i:carls)
    {
        news+=",";
        news+=QString().number(i);
        nn+=",";
        nn+=QString().number(i);
    }
    QNetworkDatagram nw(news.toUtf8(),QHostAddress("127.0.0.1"),12345);
    udp->writeDatagram(nw);
    qDebug()<<news;
    QNetworkDatagram nww(nn.toUtf8(),QHostAddress("127.0.0.1"),12345);
    udp->writeDatagram(nww);
    emit ui->mapwidget->chnoworder(orderid.toLong());
}
